#pragma once
// 对socket进行封装
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
#include <functional>
#include "Log.hpp"
#include "InetAddr.hpp"

namespace wxd
{
    class Socket;
    using SocketPtr = std::shared_ptr<Socket>;
    // 模版方法设计模式
    class Socket
    {
    public:
        virtual ~Socket() = default;
        virtual bool Create() = 0;
        virtual bool Bind() = 0;
        virtual bool Listen() = 0;
        // virtual SocketPtr Accept(InetAddrTrans &client) = 0;
        virtual int Accept(InetAddrTrans &client) = 0;
        virtual ssize_t Recv(std::string &read_string) = 0;
        virtual ssize_t Send(const std::string &write_string) = 0;
        virtual int Fd() const = 0;

        // 固定的套路
        void TcpSocketModule()
        {
            Create();
            Bind();
            Listen();
        }
    };

    class TcpSocket : public Socket
    {
        const int default_sockfd = -1;
        const int default_backlog = 8;

    private:
        bool SocketIsLegal()
        {
            return _sockfd >= 0;
        }

    public:
        TcpSocket(u_int16_t port)
            : _sockfd(default_sockfd) // 初始化sockfd
              ,
              _port(port)
        {
        }
        // 重载构造函数，用于accept返回
        TcpSocket(int sockfd)
            : _sockfd(sockfd), _port(0)
        {
        }
        ~TcpSocket() {};
        virtual bool Create() override
        {
            // 返回listen sockfd
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_sockfd < 0)
            {
                LOG(LogLevel::ERROR) << "create sockfd error!";
                exit(SOCKET_ERR);
            }
            LOG(LogLevel::INFO) << "create sockfd success! sockfd = " << _sockfd;
            // 创建成功
            return true;
        }
        // 创建socket成功后的所有操作，都要基于socket创建成功
        // 所以每一个方法都要判断一下是否socket创建成功
        // 默认绑定全部ip，需要指定端口号

        virtual bool Bind() override
        {
            LOG(LogLevel::DEBUG) << "bind port:" << _port;
            if (!SocketIsLegal())
                return false;
            InetAddrTrans local_trans(_port);
            int n = bind(_sockfd, local_trans.SockaddrPtr(), local_trans.SockLen());
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "bind error!";
                exit(BIND_ERR);
            }
            // 绑定成功
            LOG(LogLevel::INFO) << "bind success! sockfd = " << _sockfd;
            return true;
        }

        virtual bool Listen() override
        {

            if (!SocketIsLegal())
                return false;
            int n = listen(_sockfd, default_backlog);
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "listen error!";
                exit(LISTEN_ERR);
            }
            LOG(LogLevel::INFO) << "listening...";
            return true;
        }

        // // 成功返回Socket类指针(指向TcpSocket对象)，把客户端信息带出来
        // virtual SocketPtr Accept(InetAddrTrans &client) override
        // {
        //     if (!SocketIsLegal())
        //         return nullptr;
        //     // 创建新sockaddr，清空，用于接收连接信息
        //     sockaddr_in peer;
        //     bzero(&peer, sizeof(peer));
        //     socklen_t peer_len = sizeof(peer);
        //     int newsockfd = accept(_sockfd, ADDR_PTR(peer), &peer_len);
        //     if (newsockfd < 0)
        //     {
        //         LOG(LogLevel::ERROR) << "accept error!";
        //         return nullptr;
        //     }
        //     InetAddrTrans peer_trans(peer);
        //     LOG(LogLevel::INFO) << "accept a new client: " << peer_trans.AddrInfo();
        //     client = peer_trans;
        //     // 返回TcpSocket的指针，用于未来调用send，recv方法
        //     return std::make_shared<TcpSocket>(newsockfd);
        // }

        // 成功返回文件描述符
        virtual int Accept(InetAddrTrans &client) override
        {
            if (!SocketIsLegal())
                return default_sockfd;
            // 创建新sockaddr，清空，用于接收连接信息
            sockaddr_in peer;
            bzero(&peer, sizeof(peer));
            socklen_t peer_len = sizeof(peer);
            int newsockfd = accept(_sockfd, ADDR_PTR(peer), &peer_len);
            if (newsockfd < 0)
            {
                LOG(LogLevel::ERROR) << "accept error!";
                return default_sockfd;
            }
            InetAddrTrans peer_trans(peer);
            LOG(LogLevel::INFO) << "accept a new client: " << peer_trans.AddrInfo();
            client = peer_trans;
            // 返回fd
            return newsockfd;
        }

        virtual ssize_t Recv(std::string &read_string) override
        {
            if (!SocketIsLegal())
                return -1;
            char read_buffer[1024 * 8];
            ssize_t size = recv(_sockfd, read_buffer, sizeof(read_buffer), 0);
            if (size > 0)
            {
                // 暂定读到的报文是完整的
                read_string = read_buffer;
            }
            return size;
        }
        virtual ssize_t Send(const std::string &write_string) override
        {
            if (!SocketIsLegal())
                return -1;
            ssize_t size = send(_sockfd, write_string.c_str(), write_string.size(), 0);
            return size;
        }

        virtual int Fd() const override
        {
            return _sockfd;
        }

    private:
        int _sockfd;
        uint16_t _port;
    };
}